import * as THREE from 'three';
import { Vec3 } from '@/core/types';
import { Entity } from '@/entities/Entity';

// 对话气泡数据接口
interface SpeechBubble {
  id: string;
  entity: Entity;
  message: string;
  element: HTMLElement;
  startTime: number;
  duration: number;
}

// 对话气泡UI管理器
export class SpeechBubbleUI {
  private bubbles: Map<string, SpeechBubble> = new Map();
  private container!: HTMLElement;
  private camera?: THREE.Camera;
  private defaultDuration = 3000; // 3秒显示时间

  constructor() {
    this.createContainer();
    this.addStyles();
  }

  private createContainer(): void {
    this.container = document.createElement('div');
    this.container.id = 'speech-bubbles-container';
    this.container.className = 'speech-bubbles-container';
    document.body.appendChild(this.container);
  }

  private addStyles(): void {
    const style = document.createElement('style');
    style.textContent = `
      .speech-bubbles-container {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        pointer-events: none;
        z-index: 100;
      }
      
      .speech-bubble {
        position: absolute;
        background: rgba(0, 0, 0, 0.8);
        color: white;
        padding: 8px 12px;
        border-radius: 12px;
        font-family: 'Courier New', monospace;
        font-size: 14px;
        max-width: 200px;
        word-wrap: break-word;
        text-align: center;
        border: 2px solid #666;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
        transform: translate(-50%, -100%);
        animation: speechBubbleAppear 0.3s ease-out;
      }
      
      .speech-bubble::after {
        content: '';
        position: absolute;
        top: 100%;
        left: 50%;
        transform: translateX(-50%);
        border: 8px solid transparent;
        border-top-color: rgba(0, 0, 0, 0.8);
      }
      
      .speech-bubble.fade-out {
        animation: speechBubbleFadeOut 0.5s ease-in forwards;
      }
      
      @keyframes speechBubbleAppear {
        from {
          opacity: 0;
          transform: translate(-50%, -100%) scale(0.8);
        }
        to {
          opacity: 1;
          transform: translate(-50%, -100%) scale(1);
        }
      }
      
      @keyframes speechBubbleFadeOut {
        from {
          opacity: 1;
          transform: translate(-50%, -100%) scale(1);
        }
        to {
          opacity: 0;
          transform: translate(-50%, -100%) scale(0.8);
        }
      }
    `;
    document.head.appendChild(style);
  }

  /**
   * 设置相机引用（用于世界坐标到屏幕坐标转换）
   */
  public setCamera(camera: THREE.Camera): void {
    this.camera = camera;
  }

  /**
   * 显示对话气泡
   */
  public showBubble(entity: Entity, message: string, duration?: number): void {
    const bubbleId = entity.getId();
    
    // 如果该实体已有气泡，先移除
    if (this.bubbles.has(bubbleId)) {
      this.removeBubble(bubbleId);
    }

    // 创建气泡元素
    const element = document.createElement('div');
    element.className = 'speech-bubble';
    element.textContent = message;

    // 创建气泡数据
    const bubble: SpeechBubble = {
      id: bubbleId,
      entity,
      message,
      element,
      startTime: Date.now(),
      duration: duration || this.defaultDuration
    };

    // 添加到容器和映射
    this.container.appendChild(element);
    this.bubbles.set(bubbleId, bubble);

    // 更新位置
    this.updateBubblePosition(bubble);

    // 设置自动移除
    setTimeout(() => {
      this.removeBubble(bubbleId);
    }, bubble.duration);

    console.log(`显示对话气泡: ${entity.getType()} - ${message}`);
  }

  /**
   * 移除对话气泡
   */
  public removeBubble(bubbleId: string): void {
    const bubble = this.bubbles.get(bubbleId);
    if (!bubble) return;

    // 添加淡出动画
    bubble.element.classList.add('fade-out');
    
    // 动画结束后移除元素
    setTimeout(() => {
      if (bubble.element.parentNode) {
        bubble.element.parentNode.removeChild(bubble.element);
      }
      this.bubbles.delete(bubbleId);
    }, 500);
  }

  /**
   * 更新所有气泡位置
   */
  public update(): void {
    for (const bubble of this.bubbles.values()) {
      this.updateBubblePosition(bubble);
      
      // 检查是否超时
      const elapsed = Date.now() - bubble.startTime;
      if (elapsed >= bubble.duration) {
        this.removeBubble(bubble.id);
      }
    }
  }

  /**
   * 更新单个气泡位置
   */
  private updateBubblePosition(bubble: SpeechBubble): void {
    if (!this.camera) {
      // 如果没有相机，使用简单的固定位置
      bubble.element.style.left = '50%';
      bubble.element.style.top = '20%';
      return;
    }

    try {
      // 获取实体位置
      const entityPos = bubble.entity.getPosition();
      
      // 将世界坐标转换为屏幕坐标
      const screenPos = this.worldToScreen(entityPos);
      
      if (screenPos) {
        // 设置气泡位置（在实体头顶上方）
        bubble.element.style.left = `${screenPos.x}px`;
        bubble.element.style.top = `${screenPos.y - 60}px`; // 向上偏移60像素
        bubble.element.style.display = 'block';
      } else {
        // 如果实体不在屏幕内，隐藏气泡
        bubble.element.style.display = 'none';
      }
    } catch (error) {
      console.warn('更新气泡位置失败:', error);
      bubble.element.style.display = 'none';
    }
  }

  /**
   * 世界坐标转屏幕坐标
   */
  private worldToScreen(worldPos: Vec3): { x: number; y: number } | null {
    if (!this.camera) return null;

    try {
      // 创建THREE.js向量
      const vector = new THREE.Vector3(worldPos.x, worldPos.y + 2, worldPos.z); // 向上偏移2格
      
      // 投影到屏幕坐标
      vector.project(this.camera);
      
      // 转换为屏幕像素坐标
      const x = (vector.x * 0.5 + 0.5) * window.innerWidth;
      const y = (vector.y * -0.5 + 0.5) * window.innerHeight;
      
      // 检查是否在屏幕范围内
      if (x >= 0 && x <= window.innerWidth && y >= 0 && y <= window.innerHeight && vector.z < 1) {
        return { x, y };
      }
      
      return null;
    } catch (error) {
      console.warn('坐标转换失败:', error);
      return null;
    }
  }

  /**
   * 清理所有气泡
   */
  public clear(): void {
    for (const bubbleId of this.bubbles.keys()) {
      this.removeBubble(bubbleId);
    }
  }

  /**
   * 获取调试信息
   */
  public getDebugInfo(): any {
    return {
      activeBubbles: this.bubbles.size,
      bubbles: Array.from(this.bubbles.values()).map(bubble => ({
        entityId: bubble.id,
        entityType: bubble.entity.getType(),
        message: bubble.message,
        elapsed: Date.now() - bubble.startTime,
        duration: bubble.duration
      }))
    };
  }

  /**
   * 销毁UI
   */
  public dispose(): void {
    this.clear();
    if (this.container && this.container.parentNode) {
      this.container.parentNode.removeChild(this.container);
    }
  }
}